package com.qf.commons.redis.config;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.qf.commons.redis.cache.aspect.CacheAspect;
import com.qf.commons.redis.cache.listener.CacheMsgListener;
import com.qf.commons.redis.cache.standar.CacheStandarHandler;
import com.qf.commons.redis.cache.standar.cluster.RedisClusterStandarHandler;
import com.qf.commons.redis.cache.standar.local.GuavaLocalStandarHandler;
import com.qf.commons.redis.lock.aop.CLockAspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

import java.util.concurrent.TimeUnit;

/**
 * description:
 * author: Ken
 * 公众号：Java架构栈
 */
@Configuration
public class MyRedisAutoConfiguration {

    @Value("${spring.application.name}")
    private String appName;

    @Bean
    public CLockAspect getCLockAspect(){
        return new CLockAspect();
    }

    @Bean
    public CacheAspect getCacheAspect(){
        return new CacheAspect();
    }

    /**
     * 强引用 - A a = new A()
     *         如果JVM堆内存不足时，宁可报OOM异常，也不会回收强引用的对象
     * 软引用 - SoftReference<A> a = new SoftReference<>(new A());
     *         如果JVM堆内存不足时，所有软引用的对象将会被回收掉
     * 弱引用 - WeakReference
     *         无论JVM内存是否足够，只要GC扫描到弱引用就会直接回收
     * 虚引用 - PhantomReference
     *         当虚引用的对象被GC回收时，会收到一个回调
     * @return
     */
    @Bean
    public Cache<String, Object> getGuavaCache(){
        Cache<String, Object> cache = CacheBuilder.newBuilder()
                .initialCapacity(100)//初始容量大小
                .maximumSize(100000)//最大容量大小
                .expireAfterWrite(300, TimeUnit.SECONDS)//写过期时间
                .softValues()//使用软引用保存value
                .build();
        return cache;
    }

    /**
     * 本地缓存处理器
     * @return
     */
    @Bean("localCache")
    public CacheStandarHandler getLocal(){
        return new GuavaLocalStandarHandler();
    }

    /**
     * 分布式缓存处理器
     * @return
     */
    @Bean("clusterCache")
    public CacheStandarHandler getCluster(){
        return new RedisClusterStandarHandler();
    }

    /**
     * redis 发布订阅的监听容器对象
     * @return
     */
    @Bean
    public RedisMessageListenerContainer getRedisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);//设置redis连接
        container.addMessageListener(getCacheMsgListener(), new ChannelTopic("cache_channel_" + appName));
        return container;
    }

    /**
     * redis消息监听的回调方法
     * @return
     */
    @Bean
    public CacheMsgListener getCacheMsgListener(){
        return new CacheMsgListener();
    }
}
